const util = {
  
  // 求一个范围之间的随机数 
  fn: function (a,b) {
    return Math.floor(Math.random() * (b - a + 1)) + a;
  },

  //根据 id 获取元素
  my$: function (id){
    return document.getElementById(id);
  },

    /** 添加事件监听
   * @param obj <DOM object> 添加事件监听的DOM对象
   * @param type <string> 事件句柄（不带on）
   * @param fn <function> 事件处理函数
   * @param [isCapture] <boolean> 是否捕获，true代表捕获阶段处理，fasle代表冒泡，默认值是false
   */
  on: function (obj, type, fn, isCapture) {
    // 没有传递默认就是fasle
    if (isCapture === undefined) {
      isCapture = false
    }
    if (window.attachEvent) {
      // IE
      obj.attachEvent('on' + type, fn)
    } else {
      // 非IE
      obj.addEventListener(type, fn, isCapture)
    }
  },

  /** 移除事件监听
   * @param obj <DOM object> 添加事件监听的DOM对象
   * @param type <string> 事件句柄（不带on）
   * @param fn <function> 事件处理函数
   * @param [isCapture] <boolean> 是否捕获，true代表捕获阶段处理，fasle代表冒泡，默认值是false
   */
  off: function(obj, type, fn, isCapture) {
    if (isCapture === undefined) {
      isCapture = false
    }
    if (window.detachEvent) {
      obj.detachEvent('on' + type, fn)
    } else {
      obj.removeEventListener(type, fn, isCapture)
    }
  },
  
  /** 获取对象的样式
   * @param  obj  <DOM object> 要获取样式的元素对象
   * @param  attr <string>     要获取的属性名
   * @return <string>          得到的属性值
   */
  getStyle: function (obj, attr) {
    if (obj.currentStyle) {
      return obj.currentStyle[attr]
    } else {
      return getComputedStyle(obj)[attr]
    }
  },
  /** 完成元素的匀速运动
   * 
   * @param obj       <DOM object> 运动的元素对象
   * @param attr      <string>     运动的属性名
   * @param end       <number>     运动的终点值
   * @param duration  <number>     运动持续时间（单位ms）
   * @param [fn]      <function>   运动结束之后的回调函数
   */
  move: function (obj, attr, end, duration, fn) {
    // 先把之前的定时器清除掉
    clearInterval(obj.timer)
    // 1、获取起点值
    const start = parseInt(this.getStyle(obj, attr))
    // 2、计算总距离
    const distance = end - start
    // 3、计算总步数
    const steps = parseInt(duration / 20)
    // 4、计算速度（px/步） （px/20ms）
    const speed = distance / steps
    // 5、开始运动
    let n = 0 // 记录当前处于第几步
    obj.timer = setInterval(() => {
      n++
      obj.style[attr] = start + n * speed + 'px'
      if (n === steps) {
        // 运动结束
        clearInterval(obj.timer)
        // 由于速度是小数，js的小数运算可能没有那么精确，所以最后在拉到终点值
        obj.style[attr] = end + 'px'
        // 如果fn有效，才调用
        fn && fn()
      }
    }, 20)

  },

  /**实现元素的缓冲运动
   * obj  <DOM object> 运动的元素
   * attr <string>     运动的属性
   * end  <number>     运动的终点，需要一个整数
   * [fn] <function>   运动结束之后的回调函数
   */
  move2: function (obj, attr, end, fn) {
    // 先把之前的定时器清除掉
    clearInterval(obj.timer)
    // 获取起点值
    let start = parseInt(this.getStyle(obj, attr))
    // 为了确保end为整数
    end = parseInt(end)
    obj.timer = setInterval(() => {
      let distance = end - start
      // 正向运动向上取整 0.9 => 1，负向运动向下取整 -0.9 => -1
      let speed = distance > 0 ? Math.ceil(distance / 10) : Math.floor(distance / 10)
      start += speed
      obj.style[attr] = start + 'px'
      // 判断终点
      if (start === end) {
        clearInterval(obj.timer)
        fn && fn()
      }
    }, 20)
  },

  /**取cookie
   * @param key <string> 要取得cookie得名称
   * @return <string> 返回这条cookie的值，如果不存在则返返回undefined
   */
  getCookie: function (key) {
    var obj = {}
    var cookie = document.cookie
    var arr = cookie.split('; ')
    arr.forEach(item => {
      var subArr = item.split('=')
      obj[subArr[0]] = decodeURIComponent(subArr[1])
    })
    return obj[key]
  },
  
  /** 存一条cookie 
   * @param key <string>  要存的cookie的名称
   * @param value <string> 要存的cookie的值
   * @param [option] <object> { path: '/', expires: 7 }  七天过期
   */
  setCookie: function (key, value, option) {
    var str = `${key}=${encodeURIComponent(value)}`
    if (option) {
      if (option.path) {
        str += ';path=' + option.path
      }
      if (option.expires) {
        var date = new Date()
        date.setDate(date.getDate() + option.expires)
        str += ';expires=' + date.toUTCString()
      }
    }
    document.cookie = str
  },

  /**ajax get请求
   * @param url <string> 请求的路径
   * @param query <object> 请求要携带的参数
   * @param fn <function> 请求成功之后的回调函数
   * @param [isJson] <boolean> 后端返回的数据是不是json格式，默认为true
   */
  get: function (url, query, fn, isJson = true) {
    // 拼接query
    if (query) {
      url += '?'
      for (var key in query) {
        url += `${key}=${query[key]}&`
      }
      url = url.slice(0, -1)
    }

    var xhr = new XMLHttpRequest() 
    xhr.open('get', url)
    xhr.send()
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          let resp = isJson ? JSON.parse(xhr.responseText) : xhr.responseText
           fn && fn(resp)
        }
      }
    }
  },
  /**ajax get请求
   * @param url <string> 请求的路径
   * @param query <object> 请求要携带的参数
   * @param fn <function> 请求成功之后的回调函数
   * @param [isJson] <boolean> 后端返回的数据是不是json格式，默认为true
   */
  post: function (url, query, fn, isJson = true) {
    if (query) {
      var str = ''
      for (var key in query) {
        str += `${key}=${query[key]}&`
      }
      str = str.slice(0, -1)
    }

    var xhr = new XMLHttpRequest()
    xhr.open('post', url)
    xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded")
    xhr.send(str)
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          fn && fn(isJson ? JSON.parse(xhr.responseText) : xhr.responseText)
        }
      }
    }

  },
  /** josnp跨域请求
   * @param url： <string> 接口路径
   * @param cbName：  <string> 全局回调函数名
   * @param [query]： <object> 其他参数
   */
  jsonp: function (url, cbName, query) {
    url += `?cb=${cbName}`
    if (query) {
      for (var key in query) {
        url += `&${key}=${query[key]}`
      }
    }
    // 创建script
    var script = document.createElement('script')
    script.src = url
    document.body.appendChild(script)
    document.body.removeChild(script) // 过河拆桥

  },

  /**ajax promise get请求
   * @param url <string> 请求的路径
   * @param query <object> 请求要携带的参数
   * @param [isJson] <boolean> 后端返回的数据是不是json格式，默认为true
   * @return promise 数据成功返回
   */
  fetch: function (url, query, isJson = true) {
    // 拼接query
    if (query) {
      url += '?'
      for (var key in query) {
        url += `${key}=${query[key]}&`
      }
      url = url.slice(0, -1)
    }

    return new Promise((resolve, reject) => {
      var xhr = new XMLHttpRequest()
      xhr.open('get', url)
      xhr.send()
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            // 代表承诺兑现
            let resp = isJson ? JSON.parse(xhr.responseText) : xhr.responseText
            resolve(resp)
          } else {
            // 承诺失信
            reject()
          }
        }
      }
    })
  }
}

